// OpentTxl-C Version 11 bytecode converter
// J.R. Cordy, Jan 2023

// Copyright 2023, James R. Cordy and others

// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
// and associated documentation files (the “Software”), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all copies 
// or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
// AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// The OpenTxl bytecode converter.
// Converts a TXL compiled bytecode file to a standalone C byte array 
// for inclusion in a standalone application

// Modification Log

// v11.0 Initial revision, adapted from OpenTxl 11.0

// I/O, strings, memory allocation
#include "support.h"

// Runtime usage checker
static void insist (const bool cond, const string message)
{
    if (!cond) {
        fprintf (stderr, "TXL Bytecode Converter: ");
        fprintf (stderr, "%s\n", message);
        throw (QUIT);
    }
}

// Main converter program
void TProg (void) {
    // Process command line options
    bool embedded = false;
    int filearg = 1;

    string arg;
    tffetcharg (1, arg);

    if (stringcmp (arg, "-e") == 0) {
        embedded = true;
        filearg = 2;
    }

    // Get the compiled .ctxl bytecode file
    string ctxlfile;
    tffetcharg (filearg,  ctxlfile);

    insist(stringcmp (ctxlfile, "") != 0, "Usage: txlcvt [-e] file.ctxl");

    string ctxlname;
    substring (ctxlname, ctxlfile, 1, stringindex (ctxlfile, ".") - 1), stringcat (ctxlname, "_");

    string cbytefile;
    stringcpy (cbytefile, ctxlname), stringcat (cbytefile, "TXL.c");

    if (!embedded) {
        stringcpy (ctxlname, "TXL_");
    }

    int instream = 0;
    tfopen (OPEN_BINARY_READ, ctxlfile, &instream);

    string message;
    stringcpy (message, "Unable to open "), stringcat (message, ctxlfile);
    insist(instream != 0, message);

    // Read the TXL bytecode file and output it as C initialized array source 
    // for the standalone application
    int outstream = 0;
    tfopen (OPEN_CHAR_WRITE, cbytefile, &outstream);

    stringcpy (message, "Unable to create "), stringcat (message, cbytefile);
    insist(outstream != 0, message);

    fprintf (tffile (outstream), "/* TXL virtual machine byte code */\n\n");
    fprintf (tffile (outstream), "unsigned char %sTXL [] = {\n", ctxlname);
    for (int b = 1; b <= 999999999; b++) {
        if (tfeof (instream)) break;

        if (b % 20 == 0) {
            fprintf (tffile (outstream), "\n");
        }

        unsigned char byte;
        tfread (&byte, 1, instream);
        const int byteval = byte;

        fprintf (tffile (outstream), "%d,", byteval);
    }
    fprintf (tffile (outstream), "0};\n\n");

    fprintf (tffile (outstream), "unsigned char *%sCTXL = %sTXL;\n", ctxlname, ctxlname);
    tfclose (outstream);
}
